package com.cencat.common.utils;

import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 权限工具类
 * 提供权限验证、角色检查、权限计算等功能
 * 
 * @author cencat
 * @since 2024-01-01
 */
public class PermissionUtils {
    
    private static final Logger log = LoggerFactory.getLogger(PermissionUtils.class);

    private PermissionUtils() {
        // 私有构造函数，防止实例化
    }

    /**
     * 获取当前用户
     * 
     * @return 当前用户信息
     */
    public static UserDetails getCurrentUser() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null && authentication.getPrincipal() instanceof UserDetails) {
            return (UserDetails) authentication.getPrincipal();
        }
        return null;
    }

    /**
     * 获取当前用户名
     * 
     * @return 用户名
     */
    public static String getCurrentUsername() {
        UserDetails user = getCurrentUser();
        return user != null ? user.getUsername() : null;
    }

    /**
     * 获取当前用户权限列表
     * 
     * @return 权限列表
     */
    public static Set<String> getCurrentUserPermissions() {
        UserDetails user = getCurrentUser();
        if (user != null) {
            return user.getAuthorities().stream()
                    .map(GrantedAuthority::getAuthority)
                    .collect(Collectors.toSet());
        }
        return Collections.emptySet();
    }

    /**
     * 获取当前用户角色列表
     * 
     * @return 角色列表
     */
    public static Set<String> getCurrentUserRoles() {
        Set<String> permissions = getCurrentUserPermissions();
        return permissions.stream()
                .filter(permission -> permission.startsWith("ROLE_"))
                .collect(Collectors.toSet());
    }

    /**
     * 检查当前用户是否有指定权限
     * 
     * @param permission 权限标识
     * @return 是否有权限
     */
    public static boolean hasPermission(String permission) {
        if (CencatStringUtils.isBlank(permission)) {
            return false;
        }
        
        Set<String> userPermissions = getCurrentUserPermissions();
        return userPermissions.contains(permission);
    }

    /**
     * 检查当前用户是否有任意一个权限
     * 
     * @param permissions 权限列表
     * @return 是否有权限
     */
    public static boolean hasAnyPermission(String... permissions) {
        if (permissions == null || permissions.length == 0) {
            return false;
        }
        
        Set<String> userPermissions = getCurrentUserPermissions();
        return Arrays.stream(permissions)
                .anyMatch(userPermissions::contains);
    }

    /**
     * 检查当前用户是否有所有权限
     * 
     * @param permissions 权限列表
     * @return 是否有所有权限
     */
    public static boolean hasAllPermissions(String... permissions) {
        if (permissions == null || permissions.length == 0) {
            return true;
        }
        
        Set<String> userPermissions = getCurrentUserPermissions();
        return Arrays.stream(permissions)
                .allMatch(userPermissions::contains);
    }

    /**
     * 检查当前用户是否有指定角色
     * 
     * @param role 角色标识
     * @return 是否有角色
     */
    public static boolean hasRole(String role) {
        if (CencatStringUtils.isBlank(role)) {
            return false;
        }
        
        String roleWithPrefix = role.startsWith("ROLE_") ? role : "ROLE_" + role;
        Set<String> userRoles = getCurrentUserRoles();
        return userRoles.contains(roleWithPrefix);
    }

    /**
     * 检查当前用户是否有任意一个角色
     * 
     * @param roles 角色列表
     * @return 是否有角色
     */
    public static boolean hasAnyRole(String... roles) {
        if (roles == null || roles.length == 0) {
            return false;
        }
        
        return Arrays.stream(roles)
                .anyMatch(PermissionUtils::hasRole);
    }

    /**
     * 检查当前用户是否有所有角色
     * 
     * @param roles 角色列表
     * @return 是否有所有角色
     */
    public static boolean hasAllRoles(String... roles) {
        if (roles == null || roles.length == 0) {
            return true;
        }
        
        return Arrays.stream(roles)
                .allMatch(PermissionUtils::hasRole);
    }

    /**
     * 检查当前用户是否为超级管理员
     * 
     * @return 是否为超级管理员
     */
    public static boolean isSuperAdmin() {
        return hasRole(PermissionConstants.ROLE_SUPER_ADMIN) || 
               hasPermission(PermissionConstants.PERMISSION_ALL);
    }

    /**
     * 检查当前用户是否为管理员
     * 
     * @return 是否为管理员
     */
    public static boolean isAdmin() {
        return hasAnyRole(PermissionConstants.ROLE_SUPER_ADMIN, PermissionConstants.ROLE_ADMIN);
    }

    /**
     * 检查当前用户是否已认证
     * 
     * @return 是否已认证
     */
    public static boolean isAuthenticated() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        return authentication != null && authentication.isAuthenticated() && 
               !"anonymousUser".equals(authentication.getPrincipal());
    }

    /**
     * 检查当前用户是否为匿名用户
     * 
     * @return 是否为匿名用户
     */
    public static boolean isAnonymous() {
        return !isAuthenticated();
    }

    /**
     * 构建权限树
     * 
     * @param permissions 权限列表
     * @return 权限树
     */
    public static List<PermissionNode> buildPermissionTree(List<Permission> permissions) {
        if (permissions == null || permissions.isEmpty()) {
            return Collections.emptyList();
        }
        
        // 按父ID分组
        Map<Long, List<Permission>> permissionMap = permissions.stream()
                .collect(Collectors.groupingBy(permission -> permission.parentId));
        
        // 构建树形结构
        return buildPermissionTreeRecursive(permissionMap, 0L);
    }

    /**
     * 递归构建权限树
     */
    private static List<PermissionNode> buildPermissionTreeRecursive(Map<Long, List<Permission>> permissionMap, Long parentId) {
        List<Permission> children = permissionMap.get(parentId);
        if (children == null || children.isEmpty()) {
            return Collections.emptyList();
        }
        
        return children.stream()
                .map(permission -> {
                    PermissionNode node = new PermissionNode();
                    node.id = permission.id;
                    node.name = permission.name;
                    node.code = permission.code;
                    node.type = permission.type;
                    node.url = permission.url;
                    node.icon = permission.icon;
                    node.sort = permission.sort;
                    node.children = buildPermissionTreeRecursive(permissionMap, permission.id);
                    return node;
                })
                .sorted(Comparator.comparing(node -> node.sort))
                .collect(Collectors.toList());
    }

    /**
     * 获取用户可访问的权限列表
     * 
     * @param allPermissions 所有权限
     * @param userPermissions 用户权限
     * @return 可访问的权限列表
     */
    public static List<Permission> getAccessiblePermissions(List<Permission> allPermissions, Set<String> userPermissions) {
        if (allPermissions == null || allPermissions.isEmpty()) {
            return Collections.emptyList();
        }
        
        if (userPermissions == null || userPermissions.isEmpty()) {
            return Collections.emptyList();
        }
        
        return allPermissions.stream()
                .filter(permission -> userPermissions.contains(permission.code))
                .collect(Collectors.toList());
    }

    /**
     * 获取权限码列表
     * 
     * @param permissions 权限列表
     * @return 权限码列表
     */
    public static Set<String> getPermissionCodes(List<Permission> permissions) {
        if (permissions == null || permissions.isEmpty()) {
            return Collections.emptySet();
        }
        
        return permissions.stream()
                .map(permission -> permission.code)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
    }

    /**
     * 检查权限码格式是否正确
     * 
     * @param permissionCode 权限码
     * @return 是否正确
     */
    public static boolean isValidPermissionCode(String permissionCode) {
        if (CencatStringUtils.isBlank(permissionCode)) {
            return false;
        }
        
        // 权限码格式：模块:操作 或 模块:子模块:操作
        return permissionCode.matches("^[a-zA-Z][a-zA-Z0-9_]*:[a-zA-Z][a-zA-Z0-9_]*(:([a-zA-Z][a-zA-Z0-9_]*))*$");
    }

    /**
     * 权限实体类
     */
    @Data
    public static class Permission {
        private Long id;
        private String name;
        private String code;
        private String type;
        private String url;
        private String icon;
        private Integer sort;
        private Long parentId;
        private Boolean enabled;
        private String description;
    }

    /**
     * 权限节点类
     */
    @Data
    public static class PermissionNode {
        private Long id;
        private String name;
        private String code;
        private String type;
        private String url;
        private String icon;
        private Integer sort;
        private List<PermissionNode> children;
    }

    /**
     * 权限常量
     */
    public static class PermissionConstants {
        // 角色常量
        public static final String ROLE_SUPER_ADMIN = "ROLE_SUPER_ADMIN";
        public static final String ROLE_ADMIN = "ROLE_ADMIN";
        public static final String ROLE_USER = "ROLE_USER";
        public static final String ROLE_GUEST = "ROLE_GUEST";
        
        // 权限常量
        public static final String PERMISSION_ALL = "*:*";
        public static final String PERMISSION_READ = "read";
        public static final String PERMISSION_WRITE = "write";
        public static final String PERMISSION_DELETE = "delete";
        public static final String PERMISSION_EXECUTE = "execute";
        
        // 系统权限
        public static final String SYSTEM_USER_VIEW = "system:user:view";
        public static final String SYSTEM_USER_ADD = "system:user:add";
        public static final String SYSTEM_USER_EDIT = "system:user:edit";
        public static final String SYSTEM_USER_DELETE = "system:user:delete";
        
        public static final String SYSTEM_ROLE_VIEW = "system:role:view";
        public static final String SYSTEM_ROLE_ADD = "system:role:add";
        public static final String SYSTEM_ROLE_EDIT = "system:role:edit";
        public static final String SYSTEM_ROLE_DELETE = "system:role:delete";
        
        public static final String SYSTEM_PERMISSION_VIEW = "system:permission:view";
        public static final String SYSTEM_PERMISSION_ADD = "system:permission:add";
        public static final String SYSTEM_PERMISSION_EDIT = "system:permission:edit";
        public static final String SYSTEM_PERMISSION_DELETE = "system:permission:delete";
        
        // 商户权限
        public static final String MERCHANT_VIEW = "merchant:view";
        public static final String MERCHANT_ADD = "merchant:add";
        public static final String MERCHANT_EDIT = "merchant:edit";
        public static final String MERCHANT_DELETE = "merchant:delete";
        
        // 订单权限
        public static final String ORDER_VIEW = "order:view";
        public static final String ORDER_ADD = "order:add";
        public static final String ORDER_EDIT = "order:edit";
        public static final String ORDER_DELETE = "order:delete";
        public static final String ORDER_CANCEL = "order:cancel";
        public static final String ORDER_REFUND = "order:refund";
        
        // 财务权限
        public static final String FINANCE_VIEW = "finance:view";
        public static final String FINANCE_SETTLEMENT = "finance:settlement";
        public static final String FINANCE_WITHDRAW = "finance:withdraw";
        
        // 权限类型
        public static final String TYPE_MENU = "menu";
        public static final String TYPE_BUTTON = "button";
        public static final String TYPE_API = "api";
        
        private PermissionConstants() {
            // 私有构造函数
        }
    }

    /**
     * 权限验证器
     */
    public static class PermissionValidator {
        
        /**
         * 验证权限表达式
         * 
         * @param expression 权限表达式
         * @return 验证结果
         */
        public static boolean validate(String expression) {
            if (CencatStringUtils.isBlank(expression)) {
                return false;
            }
            
            try {
                // 解析权限表达式
                if (expression.contains("&&")) {
                    // AND 操作
                    String[] permissions = expression.split("&&");
                    return Arrays.stream(permissions)
                            .map(String::trim)
                            .allMatch(PermissionUtils::hasPermission);
                } else if (expression.contains("||")) {
                    // OR 操作
                    String[] permissions = expression.split("\\|\\|");
                    return Arrays.stream(permissions)
                            .map(String::trim)
                            .anyMatch(PermissionUtils::hasPermission);
                } else {
                    // 单个权限
                    return hasPermission(expression.trim());
                }
            } catch (Exception e) {
                log.error("权限表达式验证异常: {}", e.getMessage(), e);
                return false;
            }
        }
        
        /**
         * 验证角色表达式
         * 
         * @param expression 角色表达式
         * @return 验证结果
         */
        public static boolean validateRole(String expression) {
            if (CencatStringUtils.isBlank(expression)) {
                return false;
            }
            
            try {
                // 解析角色表达式
                if (expression.contains("&&")) {
                    // AND 操作
                    String[] roles = expression.split("&&");
                    return Arrays.stream(roles)
                            .map(String::trim)
                            .allMatch(PermissionUtils::hasRole);
                } else if (expression.contains("||")) {
                    // OR 操作
                    String[] roles = expression.split("\\|\\|");
                    return Arrays.stream(roles)
                            .map(String::trim)
                            .anyMatch(PermissionUtils::hasRole);
                } else {
                    // 单个角色
                    return hasRole(expression.trim());
                }
            } catch (Exception e) {
                log.error("角色表达式验证异常: {}", e.getMessage(), e);
                return false;
            }
        }
    }
}